p->domain = dom_id;
p->processor = cpu;
+ spin_lock_init(&p->blk_ring_lock);
+
p->shared_info = (void *)get_free_page(GFP_KERNEL);
memset(p->shared_info, 0, PAGE_SIZE);
SHARE_PFN_WITH_DOMAIN(virt_to_page(p->shared_info), dom_id);
+ if ( sizeof(*p->blk_ring_base) > PAGE_SIZE ) BUG();
+ p->blk_ring_base = (blk_ring_t *)get_free_page(GFP_KERNEL);
+ memset(p->blk_ring_base, 0, PAGE_SIZE);
+ SHARE_PFN_WITH_DOMAIN(virt_to_page(p->blk_ring_base), dom_id);
+
SET_GDT_ENTRIES(p, DEFAULT_GDT_ENTRIES);
SET_GDT_ADDRESS(p, DEFAULT_GDT_ADDRESS);
p->active_mm = &p->mm;
p->num_net_vifs = 0;
- INIT_LIST_HEAD(&p->io_done_queue);
- spin_lock_init(&p->io_done_queue_lock);
-
- /*
- * KAF: Passing in newdomain struct to this function is gross!
- * Therefore, for now we just allocate the single blk_ring
- * before the multiople net_rings :-)
- */
- p->blk_ring_base = (blk_ring_t *)(p->shared_info + 1);
- p->net_ring_base = (net_ring_t *)(p->blk_ring_base + 1);
+ p->net_ring_base = (net_ring_t *)(p->shared_info + 1);
INIT_LIST_HEAD(&p->pg_head);
p->tot_pages = 0;
write_lock_irqsave(&tasklist_lock, flags);
}
if ( p->mm.perdomain_pt ) free_page((unsigned long)p->mm.perdomain_pt);
+ UNSHARE_PFN(virt_to_page(p->blk_ring_base));
+ free_page((unsigned long)p->blk_ring_base);
+
UNSHARE_PFN(virt_to_page(p->shared_info));
free_page((unsigned long)p->shared_info);
virt_startinfo_addr->num_net_rings = p->num_net_vifs;
/* Add block io interface */
- virt_startinfo_addr->blk_ring = (blk_ring_t *)SH2G(p->blk_ring_base);
+ virt_startinfo_addr->blk_ring = virt_to_phys(p->blk_ring_base);
/* Copy the command line */
strcpy(virt_startinfo_addr->cmd_line, meminfo->cmd_line);
virt_startinfo_address->num_net_rings = p->num_net_vifs;
/* Add block io interface */
- virt_startinfo_address->blk_ring =
- (blk_ring_t *)SHIP2GUEST(p->blk_ring_base);
-
+ virt_startinfo_address->blk_ring = virt_to_phys(p->blk_ring_base);
/* We tell OS about any modules we were given. */
if ( nr_mods > 1 )
typedef void (*hyp_event_callback_fn_t)(void);
extern void schedule(void);
-extern void flush_blk_queue(void);
extern void update_shared_ring(void);
/* Ordering must match definitions of _HYP_EVENT_* in xeno/sched.h */
schedule,
update_shared_ring,
kill_domain,
- flush_blk_queue
};
/* Handle outstanding events for the currently-executing domain. */
{
struct list_head queue;
struct buffer_head *bh;
- blk_ring_entry_t request;
- struct task_struct *domain; /* requesting domain */
+ blk_ring_req_entry_t *request;
+ struct task_struct *domain; /* requesting domain */
} blk_request_t;
#define MAX_PENDING_REQS 256 /* very arbitrary */
static kmem_cache_t *blk_request_cachep;
-static atomic_t nr_pending, nr_done;
+static atomic_t nr_pending;
static int pending_work; /* which domains have work for us? */
void end_block_io_op(struct buffer_head * bh)
{
unsigned long cpu_mask;
- /* struct list_head *list;*/
blk_request_t *blk_request = NULL;
- unsigned long flags; /* irq save */
+ unsigned long flags;
struct task_struct *p;
+ int position = 0;
+ blk_ring_t *blk_ring;
+ int loop;
if (XEN_BLK_DEBUG)
printk(XEN_BLK_DEBUG_LEVEL "XEN end_block_io_op, bh: %lx\n",
p = blk_request->domain;
- atomic_inc(&nr_done);
- spin_lock_irqsave(&p->io_done_queue_lock, flags);
- list_add_tail(&blk_request->queue, &p->io_done_queue);
- /* enqueue work for 'flush_blk_queue' handler */
- cpu_mask = mark_hyp_event(p, _HYP_EVENT_BLK_RX);
- spin_unlock_irqrestore(&p->io_done_queue_lock, flags);
-
- /* now kick the hypervisor */
- hyp_event_notify(cpu_mask);
- return;
-
- bad_interrupt:
- printk (KERN_ALERT
- " block io interrupt received for unknown buffer [0x%lx]\n",
- (unsigned long) bh);
- BUG();
- return;
-}
-
-/*
- * flush_blk_queue
- *
- * Called by the hypervisor synchronously when there is something to do
- * (block transfers have completed)
- */
-
-void flush_blk_queue(void)
-{
- struct task_struct *p = current;
- blk_request_t *blk_request;
- int position = 0;
- blk_ring_t *blk_ring;
- unsigned long flags;
- int loop;
+ /* Place on the response ring for the relevant domain. */
+ spin_lock_irqsave(&p->blk_ring_lock, flags);
+ blk_ring = p->blk_ring_base;
+ position = blk_ring->resp_prod;
+ blk_ring->resp_ring[position].id = blk_request->request->id;
+ blk_ring->resp_ring[position].status = 0;
+ blk_ring->resp_prod = BLK_RESP_RING_INC(blk_ring->resp_prod);
+ spin_unlock_irqrestore(&p->blk_ring_lock, flags);
- spin_lock_irqsave(&p->io_done_queue_lock, flags);
- clear_bit(_HYP_EVENT_BLK_RX, &p->hyp_events);
+ /* Kick the relevant domain. */
+ cpu_mask = mark_guest_event(p, _EVENT_BLK_RESP);
+ guest_event_notify(cpu_mask);
+
+ /* Free state associated with this request. */
+ if ( blk_request->bh )
+ kfree(blk_request->bh);
+ kmem_cache_free(blk_request_cachep, blk_request);
- while ( !list_empty(&p->io_done_queue) )
- {
- blk_request = list_entry(p->io_done_queue.next, blk_request_t, queue);
- list_del(&blk_request->queue);
- spin_unlock_irqrestore(&p->io_done_queue_lock, flags);
- atomic_dec(&nr_done);
-
- /* place on ring for guest os */
- blk_ring = p->blk_ring_base;
- position = blk_ring->brx_prod;
-
- if (XEN_BLK_DEBUG)
- printk(XEN_BLK_DEBUG_LEVEL "XEN flush_blk_queue [%d]\n", position);
-
- memcpy(&blk_ring->brx_ring[position], &blk_request->request,
- sizeof(blk_ring_entry_t));
- blk_ring->brx_prod = BLK_RX_RING_INC(blk_ring->brx_prod);
-
- /* notify appropriate guest os */
- set_bit(_EVENT_BLK_RX, &p->shared_info->events);
-
- /* free the buffer header allocated in do_block_io_op */
- if ( blk_request->bh )
- kfree(blk_request->bh);
-
- kmem_cache_free(blk_request_cachep, blk_request);
-
- spin_lock_irqsave(&p->io_done_queue_lock, flags);
- }
- spin_unlock_irqrestore(&p->io_done_queue_lock, flags);
-
-
/* XXX SMH: below is ugly and dangerous -- fix */
/*
* now check if there is any pending work from any domain
}
}
- return;
+ return;
+
+ bad_interrupt:
+ printk (KERN_ALERT
+ " block io interrupt received for unknown buffer [0x%lx]\n",
+ (unsigned long) bh);
+ BUG();
+ return;
}
if (XEN_BLK_DEBUG)
printk(XEN_BLK_DEBUG_LEVEL "XEN do_block_io_op %d %d\n",
- blk_ring->btx_cons, blk_ring->btx_prod);
-
- for (loop = blk_ring->btx_cons;
- loop != blk_ring->btx_prod;
- loop = BLK_TX_RING_INC(loop)) {
+ blk_ring->req_cons, blk_ring->req_prod);
+ for ( loop = blk_ring->req_cons;
+ loop != blk_ring->req_prod;
+ loop = BLK_REQ_RING_INC(loop) )
+ {
status = 1;
- switch (blk_ring->btx_ring[loop].operation) {
+ switch (blk_ring->req_ring[loop].operation) {
case XEN_BLOCK_READ:
case XEN_BLOCK_WRITE:
default:
printk (KERN_ALERT "error: unknown block io operation [%d]\n",
- blk_ring->btx_ring[loop].operation);
+ blk_ring->req_ring[loop].operation);
BUG();
}
}
}
- blk_ring->btx_cons = loop;
+ blk_ring->req_cons = loop;
return 0L;
}
blk_ring_t *blk_ring = current->blk_ring_base;
xen_disk_info_t *xdi;
- xdi = phys_to_virt((unsigned long)blk_ring->btx_ring[index].buffer);
+ xdi = phys_to_virt((unsigned long)blk_ring->req_ring[index].buffer);
ide_probe_devices(xdi);
-
- memcpy(&blk_ring->brx_ring[blk_ring->brx_prod],
- &blk_ring->btx_ring[index],
- sizeof(blk_ring_entry_t));
- blk_ring->brx_prod = BLK_RX_RING_INC(blk_ring->brx_prod);
+
+ blk_ring->resp_ring[blk_ring->resp_prod].id = blk_ring->req_ring[index].id;
+ blk_ring->resp_ring[blk_ring->resp_prod].status = 0;
+ blk_ring->resp_prod = BLK_RESP_RING_INC(blk_ring->resp_prod);
return 0;
}
* check to make sure that the block request seems at least
* a bit legitimate
*/
- if ((blk_ring->btx_ring[index].block_size & (0x200 - 1)) != 0) {
+ if ((blk_ring->req_ring[index].block_size & (0x200 - 1)) != 0) {
printk(KERN_ALERT " error: dodgy block size: %d\n",
- blk_ring->btx_ring[index].block_size);
+ blk_ring->req_ring[index].block_size);
BUG();
}
- if(blk_ring->btx_ring[index].buffer == NULL) {
+ if(blk_ring->req_ring[index].buffer == NULL) {
printk(KERN_ALERT "xen_block: bogus buffer from guestOS\n");
BUG();
}
if (XEN_BLK_DEBUG) {
- printk(XEN_BLK_DEBUG_LEVEL " btx_cons: %d btx_prod %d index: %d "
- "op: %s, pri: %s\n", blk_ring->btx_cons, blk_ring->btx_prod,
+ printk(XEN_BLK_DEBUG_LEVEL " req_cons: %d req_prod %d index: %d "
+ "op: %s, pri: %s\n", blk_ring->req_cons, blk_ring->req_prod,
index,
- (blk_ring->btx_ring[index].operation == XEN_BLOCK_READ ?
+ (blk_ring->req_ring[index].operation == XEN_BLOCK_READ ?
"read" : "write"),
- (blk_ring->btx_ring[index].priority == XEN_BLOCK_SYNC ?
+ (blk_ring->req_ring[index].priority == XEN_BLOCK_SYNC ?
"sync" : "async"));
}
blk_request = kmem_cache_alloc(blk_request_cachep, GFP_ATOMIC);
/* we'll be doing this frequently, would a cache be appropriate? */
- /* free in flush_blk_queue */
bh = (struct buffer_head *) kmalloc(sizeof(struct buffer_head),
GFP_KERNEL);
if (!bh) {
/* set just the important bits of the buffer header */
memset (bh, 0, sizeof (struct buffer_head));
- bh->b_blocknr = blk_ring->btx_ring[index].block_number;
- bh->b_size = blk_ring->btx_ring[index].block_size;
- bh->b_dev = blk_ring->btx_ring[index].device;
- bh->b_rsector = blk_ring->btx_ring[index].sector_number;
+ bh->b_blocknr = blk_ring->req_ring[index].block_number;
+ bh->b_size = blk_ring->req_ring[index].block_size;
+ bh->b_dev = blk_ring->req_ring[index].device;
+ bh->b_rsector = blk_ring->req_ring[index].sector_number;
bh->b_data = phys_to_virt((unsigned long)
- blk_ring->btx_ring[index].buffer);
+ blk_ring->req_ring[index].buffer);
bh->b_count.counter = 1;
bh->b_xen_request = (void *)blk_request;
- if (blk_ring->btx_ring[index].operation == XEN_BLOCK_WRITE) {
+ if (blk_ring->req_ring[index].operation == XEN_BLOCK_WRITE) {
bh->b_state = ((1 << BH_JBD) | (1 << BH_Mapped) | (1 << BH_Req) |
(1 << BH_Dirty) | (1 << BH_Uptodate));
operation = WRITE;
operation = READ;
}
- /* save meta data about request XXX SMH: should copy_from_user() */
- memcpy(&blk_request->request,
- &blk_ring->btx_ring[index], sizeof(blk_ring_entry_t));
+ /* save meta data about request */
+ blk_request->request = &blk_ring->req_ring[index];
blk_request->bh = bh;
blk_request->domain = current;
static void dump_blockq(u_char key, void *dev_id, struct pt_regs *regs)
{
- printk("Dumping block queue stats:\n");
- printk("nr_pending = %d, nr_done = %d\n",
- atomic_read(&nr_pending), atomic_read(&nr_done));
+ printk("Dumping block queue stats: nr_pending = %d\n",
+ atomic_read(&nr_pending));
}
/* If bit i is true then domain i has work for us to do. */
pending_work = 0;
+
+ atomic_set(&nr_pending, 0);
}
#define XEN_BLOCK_MAX_DOMAINS 32 /* NOTE: FIX THIS. VALUE SHOULD COME FROM? */
-#define BLK_TX_RING_SIZE 256
-#define BLK_RX_RING_SIZE 256
+#define BLK_REQ_RING_SIZE 64
+#define BLK_RESP_RING_SIZE 64
-#define BLK_TX_RING_MAX_ENTRIES (BLK_TX_RING_SIZE - 2)
-#define BLK_RX_RING_MAX_ENTRIES (BLK_RX_RING_SIZE - 2)
+#define BLK_REQ_RING_MAX_ENTRIES (BLK_REQ_RING_SIZE - 2)
+#define BLK_RESP_RING_MAX_ENTRIES (BLK_RESP_RING_SIZE - 2)
-#define BLK_TX_RING_INC(_i) (((_i)+1) & (BLK_TX_RING_SIZE-1))
-#define BLK_RX_RING_INC(_i) (((_i)+1) & (BLK_RX_RING_SIZE-1))
-#define BLK_TX_RING_ADD(_i,_j) (((_i)+(_j)) & (BLK_TX_RING_SIZE-1))
-#define BLK_RX_RING_ADD(_i,_j) (((_i)+(_j)) & (BLK_RX_RING_SIZE-1))
+#define BLK_REQ_RING_INC(_i) (((_i)+1) & (BLK_REQ_RING_SIZE-1))
+#define BLK_RESP_RING_INC(_i) (((_i)+1) & (BLK_RESP_RING_SIZE-1))
+#define BLK_REQ_RING_ADD(_i,_j) (((_i)+(_j)) & (BLK_REQ_RING_SIZE-1))
+#define BLK_RESP_RING_ADD(_i,_j) (((_i)+(_j)) & (BLK_RESP_RING_SIZE-1))
-typedef struct blk_ring_entry
+typedef struct blk_ring_req_entry
{
- void * id; /* for guest os use; used for the bh */
- int priority; /* orig sched pri, SYNC or ASYNC for now */
- int operation; /* XEN_BLOCK_READ or XEN_BLOCK_WRITE */
- char * buffer;
- unsigned long block_number; /* block number */
- unsigned short block_size; /* block size */
- kdev_t device;
- unsigned long sector_number; /* real buffer location on disk */
-} blk_ring_entry_t;
+ void * id; /* for guest os use */
+ int priority; /* SYNC or ASYNC for now */
+ int operation; /* XEN_BLOCK_READ or XEN_BLOCK_WRITE */
+ char * buffer;
+ unsigned long block_number; /* block number */
+ unsigned short block_size; /* block size */
+ kdev_t device;
+ unsigned long sector_number; /* real buffer location on disk */
+} blk_ring_req_entry_t;
+
+typedef struct blk_ring_resp_entry
+{
+ void *id;
+ unsigned long status;
+} blk_ring_resp_entry_t;
typedef struct blk_ring_st
{
- blk_ring_entry_t *btx_ring;
- unsigned int btx_prod, btx_cons;
- unsigned int btx_ring_size;
-
- blk_ring_entry_t *brx_ring;
- unsigned int brx_prod, brx_cons;
- unsigned int brx_ring_size;
+ unsigned int req_prod, req_cons;
+ unsigned int resp_prod, resp_cons;
+ blk_ring_req_entry_t req_ring[BLK_REQ_RING_SIZE];
+ blk_ring_resp_entry_t resp_ring[BLK_RESP_RING_SIZE];
} blk_ring_t;
#define MAX_XEN_DISK_COUNT 100
*/
/* Events that a guest OS may receive from the hypervisor. */
-#define EVENT_BLK_TX 0x01 /* packets for transmission. */
-#define EVENT_BLK_RX 0x02 /* empty buffers for receive. */
-#define EVENT_TIMER 0x04 /* a timeout has been updated. */
-#define EVENT_DIE 0x08 /* OS is about to be killed. Clean up please! */
-#define EVENT_DEBUG 0x10 /* request guest to dump debug info (gross!) */
-#define EVENT_NET_TX 0x20 /* packets for transmission. */
-#define EVENT_NET_RX 0x40 /* empty buffers for receive. */
+#define EVENT_BLK_RESP 0x01 /* A block device response has been queued. */
+#define EVENT_TIMER 0x02 /* A timeout has been updated. */
+#define EVENT_DIE 0x04 /* OS is about to be killed. Clean up please! */
+#define EVENT_DEBUG 0x08 /* Request guest to dump debug info (gross!) */
+#define EVENT_NET_TX 0x10 /* There are packets for transmission. */
+#define EVENT_NET_RX 0x20 /* There are empty buffers for receive. */
/* Bit offsets, as opposed to the above masks. */
-#define _EVENT_BLK_TX 0
-#define _EVENT_BLK_RX 1
-#define _EVENT_TIMER 2
-#define _EVENT_DIE 3
-#define _EVENT_NET_TX 4
-#define _EVENT_NET_RX 5
-#define _EVENT_DEBUG 6
+#define _EVENT_BLK_RESP 0
+#define _EVENT_TIMER 1
+#define _EVENT_DIE 2
+#define _EVENT_NET_TX 3
+#define _EVENT_NET_RX 4
+#define _EVENT_DEBUG 5
/*
*/
typedef struct start_info_st {
unsigned long nr_pages; /* total pages allocated to this domain */
- shared_info_t *shared_info; /* start address of shared info struct */
+ shared_info_t *shared_info; /* VIRTUAL address of shared info struct */
unsigned long pt_base; /* VIRTUAL address of page directory */
- unsigned long mod_start; /* start address of pre-loaded module */
+ unsigned long mod_start; /* VIRTUAL address of pre-loaded module */
unsigned long mod_len; /* size (bytes) of pre-loaded module */
- net_ring_t *net_rings;
+ net_ring_t *net_rings; /* network rings (VIRTUAL ADDRESS) */
int num_net_rings;
- blk_ring_t *blk_ring; /* block io communication rings */
+ unsigned long blk_ring; /* block io ring (MACHINE ADDRESS) */
unsigned char cmd_line[1]; /* variable-length */
} start_info_t;
*/
tx_entry_t *tx_ring;
unsigned int tx_prod, tx_cons, tx_event;
- unsigned int tx_ring_size;
+
/*
* Guest OS places empty buffers into ring at rx_prod.
* Hypervisor fills buffers as rx_cons.
*/
rx_entry_t *rx_ring;
unsigned int rx_prod, rx_cons, rx_event;
- unsigned int rx_ring_size;
} net_ring_t;
/* Specify base of per-domain array. Get returned free slot in the array. */
-//net_ring_t *create_net_vif(int domain);
+/*net_ring_t *create_net_vif(int domain);*/
/* Packet routing/filtering code follows:
*/
#define _HYP_EVENT_NEED_RESCHED 0
#define _HYP_EVENT_NET_RX 1
#define _HYP_EVENT_DIE 2
-#define _HYP_EVENT_BLK_RX 3
#define PF_DONEFPUINIT 0x1 /* Has the FPU been initialised for this task? */
#define PF_USEDFPU 0x2 /* Has this task used the FPU since last save? */
/* Block I/O */
blk_ring_t *blk_ring_base;
- struct list_head io_done_queue;
- spinlock_t io_done_queue_lock;
+ spinlock_t blk_ring_lock;
int has_cpu, policy, counter;
static int xlblk_hardsect_size[XLBLK_MAX];
static int xlblk_max_sectors[XLBLK_MAX];
-#define XLBLK_RX_IRQ _EVENT_BLK_RX
-#define XLBLK_TX_IRQ _EVENT_BLK_TX
+#define XLBLK_RESPONSE_IRQ _EVENT_BLK_RESP
#define DEBUG_IRQ _EVENT_DEBUG
#define XLBLK_DEBUG 0
#define XLBLK_DEBUG_IOCTL 0
+static blk_ring_t *blk_ring;
+
/*
* disk management
*/
kdev_t device,
int mode)
{
- blk_ring_t *blk_ring = start_info.blk_ring;
int position;
void *buffer_pa, *buffer_ma;
kdev_t phys_device = (kdev_t) 0;
}
- if (BLK_TX_RING_INC(blk_ring->btx_prod) == blk_ring->btx_cons) {
- printk (KERN_ALERT "hypervisor_request: btx_cons: %d, btx_prod:%d",
- blk_ring->btx_cons, blk_ring->btx_prod);
+ if (BLK_REQ_RING_INC(blk_ring->req_prod) == blk_ring->req_cons) {
+ printk (KERN_ALERT "hypervisor_request: req_cons: %d, req_prod:%d",
+ blk_ring->req_cons, blk_ring->req_prod);
BUG();
}
/* Fill out a communications ring structure & trap to the hypervisor */
- position = blk_ring->btx_prod;
- blk_ring->btx_ring[position].id = id;
- blk_ring->btx_ring[position].priority = mode;
- blk_ring->btx_ring[position].operation = operation;
- blk_ring->btx_ring[position].buffer = buffer_ma;
- blk_ring->btx_ring[position].block_number = block_number;
- blk_ring->btx_ring[position].block_size = block_size;
- blk_ring->btx_ring[position].device = phys_device;
- blk_ring->btx_ring[position].sector_number = sector_number;
-
- blk_ring->btx_prod = BLK_TX_RING_INC(blk_ring->btx_prod);
+ position = blk_ring->req_prod;
+ blk_ring->req_ring[position].id = id;
+ blk_ring->req_ring[position].priority = mode;
+ blk_ring->req_ring[position].operation = operation;
+ blk_ring->req_ring[position].buffer = buffer_ma;
+ blk_ring->req_ring[position].block_number = block_number;
+ blk_ring->req_ring[position].block_size = block_size;
+ blk_ring->req_ring[position].device = phys_device;
+ blk_ring->req_ring[position].sector_number = sector_number;
+
+ blk_ring->req_prod = BLK_REQ_RING_INC(blk_ring->req_prod);
switch(mode) {
/* is there space in the tx ring for this request?
* if the ring is full, then leave the request in the queue
*
- * THIS IS A BIT BOGUS SINCE XEN COULD BE UPDATING BTX_CONS
+ * THIS IS A BIT BOGUS SINCE XEN COULD BE UPDATING REQ_CONS
* AT THE SAME TIME
*/
- {
- blk_ring_t *blk_ring = start_info.blk_ring;
-
- if (BLK_RX_RING_INC(blk_ring->btx_prod) == blk_ring->btx_cons)
- {
- printk (KERN_ALERT "OOPS, TX LOOKS FULL cons: %d prod: %d\n",
- blk_ring->btx_cons, blk_ring->btx_prod);
- BUG();
- break;
- }
- }
+ if (BLK_RESP_RING_INC(blk_ring->req_prod) == blk_ring->req_cons)
+ {
+ printk (KERN_ALERT "OOPS, TX LOOKS FULL cons: %d prod: %d\n",
+ blk_ring->req_cons, blk_ring->req_prod);
+ BUG();
+ break;
+ }
req->errors = 0;
blkdev_dequeue_request(req);
revalidate: xenolinux_block_revalidate,
};
-static void xlblk_rx_int(int irq, void *dev_id, struct pt_regs *ptregs)
+static void xlblk_response_int(int irq, void *dev_id, struct pt_regs *ptregs)
{
- blk_ring_t *blk_ring = start_info.blk_ring;
struct request *req;
int loop;
u_long flags;
- for (loop = blk_ring->brx_cons;
- loop != blk_ring->brx_prod;
- loop = BLK_RX_RING_INC(loop)) {
+ for (loop = blk_ring->resp_cons;
+ loop != blk_ring->resp_prod;
+ loop = BLK_RESP_RING_INC(loop)) {
- blk_ring_entry_t *bret = &blk_ring->brx_ring[loop];
+ blk_ring_resp_entry_t *bret = &blk_ring->resp_ring[loop];
- if(bret->operation == XEN_BLOCK_PROBE)
- continue;
+ req = (struct request *)bret->id;
+ if ( req == NULL ) continue; /* probes have NULL id */
spin_lock_irqsave(&io_request_lock, flags);
- req = (struct request *)bret->id;
if (!end_that_request_first(req, 1, "XenBlk"))
end_that_request_last(req);
}
- blk_ring->brx_cons = loop;
+ blk_ring->resp_cons = loop;
}
-static void xlblk_tx_int(int irq, void *dev_id, struct pt_regs *ptregs)
-{
- if (XLBLK_DEBUG)
- printk (KERN_ALERT "--- xlblock::xlblk_tx_int\n");
-}
int __init xlblk_init(void)
{
- blk_ring_t *blk_ring = start_info.blk_ring;
int loop, error, result;
- /* initialize memory rings to communicate with hypervisor */
- if ( blk_ring == NULL ) return -ENOMEM;
+ /* This mapping was created early at boot time. */
+ blk_ring = (blk_ring_t *)FIX_BLKRING_BASE;
- blk_ring->btx_prod = blk_ring->btx_cons = 0;
- blk_ring->brx_prod = blk_ring->brx_cons = 0;
- blk_ring->btx_ring = NULL;
- blk_ring->brx_ring = NULL;
-
- blk_ring->btx_ring = kmalloc(BLK_TX_RING_SIZE * sizeof(blk_ring_entry_t),
- GFP_KERNEL);
- blk_ring->brx_ring = kmalloc(BLK_RX_RING_SIZE * sizeof(blk_ring_entry_t),
- GFP_KERNEL);
-
- if ((blk_ring->btx_ring == NULL) || (blk_ring->brx_ring == NULL)) {
- printk (KERN_ALERT "could not alloc ring memory for block device\n");
- error = -ENOBUFS;
- goto fail;
- }
+ blk_ring->req_prod = blk_ring->req_cons = 0;
+ blk_ring->resp_prod = blk_ring->resp_cons = 0;
- error = request_irq(XLBLK_RX_IRQ, xlblk_rx_int, 0,
- "xlblk-rx", &xlblk_device);
+ error = request_irq(XLBLK_RESPONSE_IRQ, xlblk_response_int, 0,
+ "xlblk-response", &xlblk_device);
if (error) {
printk(KERN_ALERT "Could not allocate receive interrupt\n");
goto fail;
}
- error = request_irq(XLBLK_TX_IRQ, xlblk_tx_int, 0,
- "xlblk-tx", &xlblk_device);
- if (error) {
- printk(KERN_ALERT "Could not allocate transmit interrupt\n");
- free_irq(XLBLK_RX_IRQ, &xlblk_device);
- goto fail;
- }
-
memset (&xen_disk_info, 0, sizeof(xen_disk_info));
xen_disk_info.count = 0;
return 0;
fail:
- if (blk_ring->btx_ring) kfree(blk_ring->btx_ring);
- if (blk_ring->brx_ring) kfree(blk_ring->brx_ring);
return error;
}
/******************************************************************/
static struct proc_dir_entry *bdt;
-static blk_ring_entry_t meta;
+static blk_ring_req_entry_t meta;
static char * data;
static int proc_read_bdt(char *page, char **start, off_t off,
if (pte_val(*pte))
pte_ERROR(*pte);
pgprot_val(prot) = pgprot_val(PAGE_KERNEL) | pgprot_val(flags);
- set_pte(pte, mk_pte_phys(phys, prot));
+
+ /* We queue directly, avoiding hidden phys->machine translation. */
+ queue_l1_entry_update(__pa(pte), phys | pgprot_val(prot));
/*
* It's enough to flush this one mapping.
__flush_tlb_one(vaddr);
}
+void __set_fixmap (enum fixed_addresses idx, unsigned long phys,
+ pgprot_t flags)
+{
+ unsigned long address = __fix_to_virt(idx);
+
+ if (idx >= __end_of_fixed_addresses) {
+ printk("Invalid __set_fixmap\n");
+ return;
+ }
+ set_pte_phys(address, phys, flags);
+}
+
+static void __init fixrange_init (unsigned long start,
+ unsigned long end, pgd_t *pgd_base)
+{
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+ int i, j;
+ unsigned long vaddr;
+
+ vaddr = start;
+ i = __pgd_offset(vaddr);
+ j = __pmd_offset(vaddr);
+ pgd = pgd_base + i;
+
+ for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) {
+ pmd = (pmd_t *)pgd;
+ for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) {
+ if (pmd_none(*pmd)) {
+ pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(pte)));
+ if (pte != pte_offset(pmd, 0))
+ BUG();
+ }
+ vaddr += PMD_SIZE;
+ }
+ j = 0;
+ }
+
+ XENO_flush_page_update_queue();
+}
+
void __init paging_init(void)
{
unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
unsigned int max_dma, high, low;
+ unsigned long vaddr;
max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
low = max_low_pfn;
zones_size[ZONE_NORMAL] = low - max_dma;
}
free_area_init(zones_size);
+
+ /*
+ * Fixed mappings, only the page table structure has to be created -
+ * mappings will be set by set_fixmap():
+ */
+ vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
+ fixrange_init(vaddr, 0, init_mm.pgd);
+
+ /*
+ * XXX We do this conversion early, so that all other page tables
+ * will automatically get this mapping.
+ */
+ set_fixmap(FIX_BLKRING_BASE, start_info.blk_ring);
}
#include <asm/processor.h>
#include <asm/hypervisor.h>
#include <linux/threads.h>
+#include <asm/fixmap.h>
#ifndef _I386_BITOPS_H
#include <asm/bitops.h>
#define VMALLOC_START (((unsigned long) high_memory + 2*VMALLOC_OFFSET-1) & \
~(VMALLOC_OFFSET-1))
#define VMALLOC_VMADDR(x) ((unsigned long)(x))
-#define VMALLOC_END (HYPERVISOR_VIRT_START-PAGE_SIZE)
+#define VMALLOC_END (FIXADDR_START - 2*PAGE_SIZE)
#define _PAGE_BIT_PRESENT 0
#define _PAGE_BIT_RW 1